from django.shortcuts import render
from django import http
from django.views import View
from QQLoginTool.QQtool import OAuthQQ
from django.conf import settings
from apps.oauth.models import OAuthQQUser
from django.contrib.auth import login, authenticate, logout
from apps.oauth.utils import generate_access_token_openid, check_access_token_openid
import json, re
from django_redis import get_redis_connection
from apps.users.models import User


# Create your views here.



class QQUserView(View):
    """用户扫码登录的回调处理"""

    def get(self, request):
        """Oauth2.0认证"""
        # 获取前端发送过来的 code 参数:
        code = request.GET.get('code')

        if not code:
            # 判断 code 参数是否存在
            return http.JsonResponse({'code': 400,
                                      'errmsg': '缺少code参数'})

            # 调用我们安装的 QQLoginTool 工具类
            # 创建工具对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                        client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI)
        try:
            #使用code获取access_token
            access_token = oauth.get_access_token(code)

            #使用access_token获取openID
            openid = oauth.get_open_id(access_token)
        except Exception as e:
            return http.JsonResponse({'code':400,
                                      'errmsg':'OAuth2.0认证失败'})

        #使用openID判断当前qq用户是否是已经绑定过美多商城用户
        try:
            oauth_model = OAuthQQUser.objects.get(openid=openid)

        except OAuthQQUser.DoesNotExist:
            # 未绑定用户重定向到绑定页面
            #将openID还给用户保存将来绑定时在传过来
            access_token_openid = generate_access_token_openid(openid)
            return http.JsonResponse({'code':300,
                                      'errmsg':'用户未绑定',
                                      'access_token':access_token_openid})

        else:
            #实现QQ登录时,真正登录到美多商城的不是QQ用户而是QQ用户绑定的美多商城用户
            #已绑定用户实现状态保持user=绑定美多的用户(qq模型对象.外件)
            login(request, user=oauth_model.user)

            #实现状态保持
            response = http.JsonResponse({'code':0,
                                      'errmsg':'ok'})
            response.set_cookie('username', oauth_model.user.username, max_age=3600*24*14)

            #合并购物车
            from apps.carts.utils import merge_cart_cookie_to_redis
            response = merge_cart_cookie_to_redis(request,oauth_model.user, response)

            return response


    def post(self, request):
        """
        openid绑定用户逻辑
        :param request:
        :return:
        """
        #接受参数
        user_dict = json.loads(request.body.decode())
        mobile = user_dict.get('mobile')
        password = user_dict.get('password')
        sms_code_client = user_dict.get('sms_code')
        access_token = user_dict.get('access_token')

        #校验参数
        if not all([mobile, password, sms_code_client, access_token]):
            return http.JsonResponse({'code': 400,
                                      'errmsg': '缺少必传参数'})

        # 判断mobile
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.JsonResponse({'code': 400,
                                      'errmsg': '手机号格式错误'})

        # 判断password
        if not re.match(r'^[a-zA-Z0-9]{8,20}$', password):
            return http.JsonResponse({'code': 400,
                                      'errmsg': '密码格式不符'})

        # 判断服务的短信是否存在,提取数据库短信
        redis_conn = get_redis_connection('verify_code')
        sms_code_server = redis_conn.get('sms_%s' % mobile)

        #判断短信验证码是否过期
        if not sms_code_server:
            return http.JsonResponse({'code': 400,
                                      'errmsg': '短信验证码失效'})

        #对比用户输入和服务器存储的短信验证码是否一致
        if sms_code_server.decode() != sms_code_client:
            return http.JsonResponse({'code': 400,
                                      'errmsg': '短信验证码错误'})

        #获取openID
        openid = check_access_token_openid(access_token)

        # 判断openID
        if not openid:
            return http.JsonResponse({'code': 400,
                                      'errmsg': '参数openID有误'})

        # 实现核心逻辑
        # 判断手机号是否存在,
        try:
            user = User.objects.get(mobile=mobile)

        except User.DoesNotExist:
            # 不存在注册绑定
            user = User.objects.create_user(username=mobile, password=password, mobile=mobile)

        else:
            # 存在校验密码
            if not user.check_password(password):
                return http.JsonResponse({'code': 400,
                                          'errmsg': 'password有误'})

        #将上面得到的用户和openID进行绑定
        #create_user:只有继承AbstractUser的用户模型类才可以去调用,创建用户记录
        #create:凡是继承自model的模型类都可以调用,用来创建记录
        try:
            OAuthQQUser.objects.create(user=user, openid=openid)
        except Exception as e:
            return http.JsonResponse({'code': 400,
                                      'errmsg': 'QQ登录失败'})

        #状态保持
        login(request, user)

        # 注册成功后用户名写入cookie
        response = http.JsonResponse({'code': 0,
                                      'errmsg': 'ok'})
        response.set_cookie('username', user.username, max_age=3600 * 24 * 14)

        # 响应结果
        return response


class QQURLView(View):
    #qq登录扫码链接
    #GET /qq/authorization/

    def get(self, request):
        #接受next参数
        next =request.GET.get('next', '/')


        #创建oauthqq对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                        client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI,
                        state=next)

        #调用提供的qq登录扫码登录接口函数
        login_url = oauth.get_qq_url()
        #响应结果
        return http.JsonResponse({'code':0,
                                  'errmsg':'ok',
                                  'login_url':login_url})
